package com.songwo.shiro;

import com.songwo.common.Constant;
import com.songwo.core.primary.entity.system.SysRole;
import com.songwo.core.primary.entity.system.SysUser;
import com.songwo.core.service.system.SysUserService;
import com.songwo.util.EncryptUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zhongzheng
 * @description 自定义realm
 * @date 2018/5/28 0028 17:18
 */
public class MyShiroRealm extends AuthorizingRealm {

    @Resource
    private SysUserService sysUserService;

    /**
     * 授权用户权限
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        SysUser sysUser = (SysUser) principals.getPrimaryPrincipal();
        // 取得用户的角色列表
        Set<SysRole> sysRoles = sysUser.getSysRoles();
        Set<String> roleSet = sysRoles.parallelStream().map(SysRole::getRoleName).collect(Collectors.toSet());
        info.setRoles(roleSet);
        // 取得用户的权限列表
        Set<String> permissionSet = new HashSet<>();
        for (SysRole sysRole : sysRoles) {
            sysRole.getPermissionSet().stream().forEach(sysPermission -> {
                permissionSet.add(sysPermission.getPermissionName());
            });
        }
        info.setStringPermissions(permissionSet);

        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String loginName = (String) token.getPrincipal();
        SysUser sysuser = sysUserService.findSysUserByName(loginName);
        if (sysuser != null) {
            if (Constant.LOCKED.equals(sysuser.getLockFlag())) {
                throw new LockedAccountException("该用户已经被锁定不能登录，请与管理员联系！");
            }
            if (Constant.DELETED.equals(sysuser.getDelFlag())) {
                throw new DisabledAccountException("该用户已被禁用！");
            }
            String salt = EncryptUtil.base64Decode(StringUtils.substring(sysuser.getPassword(), 0, 16));
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(loginName,
                    StringUtils.substring(sysuser.getPassword(), 16), ByteSource.Util.bytes(salt), getName());

            // 当验证都通过后，把用户信息放在session里
            Session session = SecurityUtils.getSubject().getSession();
            session.setAttribute("user", sysuser);
            session.setAttribute("userId", sysuser.getId());

            return info;
        } else {
            throw new AuthenticationException("用户名或密码不正确！");
        }
    }
}
